import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Button, Switch, message, Icon } from 'antd';

import { htmlToAST, astToHtml } from './../../utils/htmlAnalyse';
const Base64 = require('js-base64').Base64;

const string = PropTypes.string.isRequired;
const func = PropTypes.func.isRequired;

const link = document.createElement('link');
link.rel = "stylesheet";
link.type = "text/css";
document.head.appendChild(link);

export default class RenderArea extends Component {
  static propTypes = {
    html: string,
    css: string,
    onBegin: func,
    onEnd: func,
    onChange: func
  }
  state = {
    i: 0,// 表示手动操作当前的偏移量
    rdom: '',
    duration: 1000,
    menual: true
  }
  componentDidMount() {
    let css = this.props.css.replace(/\n/g, '');
    link.href = 'data:text/css;base64, ' + Base64.encode(css);
  }
  componentDidUpdate() {
    let css = this.props.css.replace(/\n/g, '');
    link.href = 'data:text/css;base64, ' + Base64.encode(css);
  }
  componentWillUnmount() {
    // style.innerHTML = '';
  }
  beginRender = (i) => {
    let ast = htmlToAST(this.props.html);
    // console.log(ast);
    clearTimeout(this.timer);
    this.props.onBegin();
    if(this.state.menual) {
      this.startMenual(ast, i);
    }
    else {
      this.startAnimation(ast, 1);
    }
  }
  startMenual(ast, i) {
    if(i < 0) {
      this.props.onEnd();
      message.warning('已经什么都没有啦');
      return;
    }
    let { rdom, copy } = this.getrDOM(ast, i);
    this.setState({ rdom });
    let html = astToHtml(copy);
    this.props.onChange(html);
    if(this.done) {
      this.props.onEnd();
      message.warning('在怎么找也没有啦');
      return;
    }
    this.setState({ i });
  }
  startAnimation(ast, i) {
    // 生成reactDOM
    let { rdom, copy } = this.getrDOM(ast, i);
    this.setState({ rdom });
    let html = astToHtml(copy);
    this.props.onChange(html);
    if(this.done) {
      this.props.onEnd();
      message.warning('已全部渲染');
      return;
    }
    // 定时递归
    this.timer = setTimeout(() => {
      this.startAnimation(ast, i + 1);
    }, this.state.duration);
  }
  getrDOM(ast, total) {
    if(total < 1) {return "";}
    // if(total === 1) {
    //   // console.log(ast.name, ast.attribs);
    //   return React.createElement(ast.name, ast.attribs);
    // }
    let copy = {};
    this.count = total - 1;
    this.copyAst(ast, copy);
    this.done = this.count > 0;
    // console.log(this.count);

    // console.log(copy);
    return {
      rdom: this.createElement(copy),
      copy
    };
  }
  /**
   * 根据html的ast语法树生成reactDOM
   * @param {*} ast
   */
  createElement(ast, key) {
    key = key || 1000;
    return React.createElement(ast.name, {...ast.attribs, key}, ast.children.map((child, index) => {
      if(typeof child === 'string') {
        return child;
      }
      return this.createElement(child, key + 1 + index);
    }));
  }
  /**
   * 深度优先搜索树
   * 根据要求的count值决定拷贝的数量
   * @param {*} ast
   * @param {*} copy
   */
  copyAst(ast, copy) {
    Object.assign(copy, ast);
    copy.children = [];
    if(this.count <= 0) {
      return;
    }
    ast.children.forEach(child => {
      if(this.count <= 0) {return;}
      this.count --;
      if(typeof child === 'string') {
        copy.children.push(child);
        return;
      }
      let cur = {};
      copy.children.push(cur);
      this.copyAst(child, cur);
    });
  }
  onChange = (menual) => {
    this.setState({
      i: 0,
      menual,
      rdom: ""
    });
    clearTimeout(this.timer);
    this.props.onEnd && this.props.onEnd();
    this.props.onSwitch && this.props.onSwitch();
  }
  render() {
    return (
      <div className="render-box">
        <div className="render-btn-list">
          <Switch checkedChildren="手动" unCheckedChildren="自动" defaultChecked onChange={this.onChange}/>
          {this.state.menual? (<Button.Group size='small'>
            <Button type="primary" onClick={() => this.beginRender(this.state.i - 1)}>
              <Icon type="left" />
              上一步
            </Button>
            <Button type="primary" onClick={() => this.beginRender(this.state.i + 1)}>
              下一步
              <Icon type="right" />
            </Button>
          </Button.Group>): <Button type="primary" size="small" onClick={this.beginRender}>渲染</Button>
          }
        </div>
        <div className="render-area">
          {/* <div className="render-container" dangerouslySetInnerHTML={ { __html: this.props.html } }></div> */}
          <div className="render-container">
            { this.state.rdom }
          </div>
        </div>
      </div>
    )
  }
}
